Skip to content

fix: runner on patched Node 24.22.1+ (CVE-2026-111497) - #30

Merged
birme merged 1 commit into
mainfrom
cve-2026-111497-node-24
Oct 23, 2026
Merged

birme merged 1 commit into
mainfrom
cve-2026-111497-node-24

Conversation

@birme

@birme birme commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Closes #29

What changes

Dockerfile only: NodeSource setup script setup_lts.x -> setup_24.x (keeps apt-get install -y nodejs, no exact pin), plus a build gate in the same RUN that fails the image build if Node is below 24.22.1 and prints node --version. With the gate, a dev or prod remake can only reach DONE on Node >= 24.22.1. No test for the Dockerfile text; the build gate and the merge-triggered "Sync fork in dev" run are the automated checks.

What changes for existing consumers

Node 24.20.0 / 24.21.0 -> >= 24.22.1, same major. Python code is unaffected. Tenant code that starts Node gets the patched version on its next restart on the new tag. Pinning to setup_24.x also stops a silent move to the next LTS major.

Brotli path (AC3)

The runner's own Node use is the @osaas/cli config-to-env call at scripts/docker-entrypoint.sh:232 (platform hosts only). node/npm/npx are on PATH, so a tenant app that starts Node and decodes attacker-controlled Brotli is the tenant's own path; the platform cannot see it.

Scope reductions

cut citation owning ticket decision owner
python-runner-orchestrator rebuild (AC1/AC2 orchestrator half) birme, web-runner#67 comment 2026-10-23 12:54Z ("deferred"); osaas-lib-orchestrator#319 body Eyevinn/osaas-lib-orchestrator#319 (AC2 + AC3) birme

The orchestrator image comes from the osaas-maker template, not from files in this repo. The post-merge dev read below is not a gate; a lower orchestrator reading means waiting for #319's pin.

Post-merge check (agent, read-only)

  • "Sync fork in dev" run for the merge commit has conclusion success.
  • eyevinn-osaas-dev/python-runner:latest label io.osaas.repo.commit equals the merge SHA; the NodeSource RUN layer's var/lib/dpkg/status has Package: nodejs Version: >= 24.22.1.
  • python-runner-orchestrator:latest created after the merge; read NODE_VERSION (expected >= 22.23.4; if lower, post the value on osaas-lib-orchestrator#319).

What a human does next

  1. Publish a python-runner GitHub release from main after the merge so sync-fork-prod.yml syncs the prod fork and remakes. Expected: prod :latest (54 tenants) has nodejs >= 24.22.1.
  2. Promoting :latest to :stable for the 53 pinned tenants is birme's call (see osaas-deploy-manager#1867 for the earlier plan shape).

Lessons

setup_lts.x floats with NodeSource's LTS pointer and the Node version was never pinned, so the image's Node depended on build day; an in-RUN version gate is the only check available since the repo has no image-build CI and the runner has no docker.

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

Co-Authored-By: Claude <noreply@anthropic.com>
@birme birme self-assigned this Oct 23, 2026
@birme

birme commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Research Review

Verified

  • Dockerfile hunk: setup_lts.x to setup_24.x. The live NodeSource setup_24.x script sets NODE_VERSION="24.x" (fetched 2026-10-23). The architect triage confirmed that the node_24.x index lists 24.22.1.
  • Build gate logic: I ran the M!==24||m<22||(m===22&&p<1) expression against sample versions. 24.22.1 and 24.23.0 pass; 24.22.0, 24.21.0, 25.0.0 and 24.9.9 fail. It behaves as the PR body says.
  • The gate sits in the same RUN as the install and is chained with &&, so a failure aborts the build.
  • Premise for the Brotli statement (AC3): the issue and triage place the only runner Node use at scripts/docker-entrypoint.sh:232, and the PR body repeats that. The body states that tenant code decides its own Brotli exposure, which is what AC3 asks for.
  • Scope reductions row: it cites birme's web-runner#67 comment and the osaas-lib-orchestrator#319 body, as recorded in the 18:15Z issue comment. This resolves architect-reviewer BLOCK findings 1 to 3 (post-merge read marked "not a gate", lower orchestrator reading means waiting for #319).
  • Lessons section is present and filled in. PR body carries the Claude attribution trailer.

Adjacent Stubs Detected

  • None. The only touched file is Dockerfile, and it has no stub patterns.

Orphaned Files Detected

  • None. Dockerfile is an entry point.

Escape Hatch Coverage

  • Dockerfile gate: process.exit(1) when Node is below 24.22.1. This is a build-time guard, not a user-facing rejection. No legitimate user action is blocked. The only way to hit it is a NodeSource package older than the fix, which is the intended failure.
  • Risk worth noting, not blocking: if NodeSource ever withdraws or lags 24.22.1+, the dev and prod remakes fail rather than silently ship a vulnerable image. That is the intended fail-loud behaviour. The gate also rejects Node 25 and later by design (M!==24). A deliberate move to 26 would need the gate edited.

Object Shape Verification

  • No spreads or re-serialisation in the diff.

Contract diff

  • No request handler or timeout changed. Files checked: Dockerfile only. The runtime Node patch version changes within major 24.

Existing consumers

  • Not a compliance/standards PR. The PR body states Node 24.20/24.21 to at least 24.22.1 with the same major, and Python code is unaffected.

Impact Analysis

  • Blast radius: the python-runner image, covering the 53 tenants on stable and 54 on latest. Pinned stable tenants are unaffected until birme promotes :latest.
  • Downstream consumers: tenant code that starts Node gets the patched version on its next restart on the new tag. The @osaas/cli call in the entrypoint runs on the new Node. I did not check other repos, since this is a single-file Dockerfile change.
  • Coordinated changes needed: none for merge. The prod release, which publishes a GitHub release to trigger sync-fork-prod.yml, is birme's call. The python-runner-orchestrator image is deferred to osaas-lib-orchestrator#319.
  • Breaking change risk: low. It is a patch-level Node bump in the same major.

Risks Not Tested

  • The image build itself was not run. There is no image-build CI in this repo (gh pr checks reports no checks) and the reviewer has no docker. The build gate and the merge-triggered "Sync fork in dev" run are the only checks.
  • Whether the apt-installed nodejs resolves to a version at or above 24.22.1 (NodeSource publishes two package suffixes for 24.22.1) is only confirmed through the NodeSource index per the triage.
  • The post-merge dev read of the runner and orchestrator images was not performed. It is stated as not a gate.
  • Brotli reachability in tenant code is unknowable from this repo.

Research Suggestions

  • After merge, confirm the "Sync fork in dev" run succeeded and that the dev image's nodejs is at least 24.22.1, as the PR body lists.

Verdict

No blocking issues found.


Reviewed by PR Research Validator. This review checks whether code is based on verified sources rather than assumptions.

@birme
birme merged commit 2658f1f into main Oct 23, 2026
@birme
birme deleted the cve-2026-111497-node-24 branch October 23, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[P0] CVE-2026-111497 (Node Brotli RCE) - runner on patched Node

2 participants